use async_graphql::{scalar, SimpleObject};
use linera_sdk::{
    linera_base_types::{AccountOwner, Amount},
    views::{linera_views, MapView, RegisterView, RootView, ViewStorageContext},
};
use serde::{Deserialize, Serialize};

use crowd_funding::InstantiationArgument;

/// The status of a crowd-funding campaign
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
pub enum Status {
    /// The campaign is active and can receive pledges.
    #[default]
    Active = 0,
    /// The campaign has ended successfully and can still receive additional pledges.
    Complete = 1,
    /// The campaign was cancelled, all pledges have been returned and no more pledges can be made.
    Cancelled = 2,
}

scalar!(Status);

/// The crowd-funding campaign's state
#[derive(RootView, SimpleObject)]
#[view(context = "ViewStorageContext")]
pub struct CrowdFundingState {
    /// The status of the campaign
    pub status: RegisterView<Status>,
    /// The map of pledges that will be collected if the campaign succeeds
    pub pledges: MapView<AccountOwner, Amount>,
    /// The instantiation data that determines the details of the campaign
    pub instantiation_argument: RegisterView<Option<InstantiationArgument>>,
}

#[allow(dead_code)]
impl Status {
    /// Returns `true` if the campaign status is [`Status::Complete`]
    pub fn is_complete(&self) -> bool {
        matches!(self, Status::Complete)
    }
}
